#pragma once
#include "core_headers.hpp"
#include "Poller.hpp"
#include "Channel.hpp"
#include "TimerWheel.hpp"
// 保证每一个链接都在一个线程中，但是如果在多线程中，分摊了这个链接的任务，而这写任务有封装的Send操作，而这封装的Send操作是共享资源，
// 会引发线程安全，所以，把这些操作压入任务队列中，然后对任务队列加锁，然后统一执行队列操作

using Functor = std::function<void()>;

class EventLoop
{
private:
	void RunAllTast()
	{
		std::vector<Functor> tmp;
		{
			std::unique_lock<std::mutex> lock(_mutex);
			_tasks.swap(tmp);
		}
		for (auto &e : tmp)
		{
			e();
		}
	}
	// 不需要eventloop内操作，不需要this
	static int CreateEventfd()
	{
		int ret = ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
		if (ret < 0)
		{
			ERR_LOG("eventfd error,%d,%s", errno, strerror(errno));
			abort();
		}
		return ret;
	}
	// 读进行消费，内容置为0
	void ReadEventfd()
	{
		uint64_t val = 0;
		int ret = ::read(_event_fd, &val, sizeof(val));
		if (ret < 0)
		{
			// EINTR -- 被信号打断； EAGAIN -- 表⽰⽆数据可读
			if (errno == EINTR || errno == EAGAIN)
			{
				return;
			}
			ERR_LOG("eventfd read error,%d,%s", errno, strerror(errno));
			abort();
		}
		return;
	}
	// 写进行唤醒事件描述符
	void WeakUpEventFd()
	{
		uint64_t val = 1;
		int ret = ::write(_event_fd, &val, sizeof(val));
		if (ret < 0)
		{
			if (errno == EINTR)
			{
				return;
			}
			ERR_LOG("eventfd write error,%d,%s", errno, strerror(errno));
			abort();
		}
	}

public:
	EventLoop()
		: _timer_wheel(this), _thread_id(std::this_thread::get_id()), _event_fd(CreateEventfd()), _event_channel(new Channel(this, _event_fd))
	{
		_event_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd, this));
		_event_channel->EnableReadableEvent();
	}
	void Start()
	{
		while (1)
		{
			// 事件监控  就绪事件处理，执行任务
			std::vector<Channel *> active;
			poller.OpenPoll(&active);
			for (auto &e : active)
			{
				e->HandlerEvent();
			}
			RunAllTast();
		}
	}
	// 判断当前线程是否是EventLoop对应的线程
	bool IsInLoop()
	{
		return (std::this_thread::get_id() == _thread_id);
	}
	void AssertInLoop()
	{
		assert(_thread_id == std::this_thread::get_id());
	}
	// 判断当前任务是不是在当前线程中，如果在直接执行，不在则压入任务队列
	void RunInLoop(const Functor &cd)
	{
		if (IsInLoop())
		{
			return cd(); // 要直接返回，不然又插入队列，此时Channel被销毁后，队列里面又有任务，执行任务就会报错
		}
		return QueueInLoop(cd);
	}
	// 把任务压入队列
	void QueueInLoop(const Functor &cd)
	{
		// 对队列进行操作要进行加锁
		{
			std::unique_lock<std::mutex> lock(_mutex);
			_tasks.push_back(cd);
		}
		// 把任务插入队列中，有有可能epoll_wait等待就绪事件可能发生阻塞要进行唤醒
		WeakUpEventFd();
	}
	// 添加/修改描述符监控
	void UpdateEvents(Channel *channel)
	{
		return poller.UpdateEvents(channel);
	}
	// 移除描述符监控
	void RemoveEvents(Channel *channel)
	{
		return poller.RemoveEvents(channel);
	}
	// 添加定时任务
	void TaskAdd(uint64_t id, uint32_t timeout, const TaskFunc &task)
	{
		_timer_wheel.TaskAdd(id, timeout, task);
	}
	void RefreshTask(uint64_t id)
	{
		_timer_wheel.RefreshTask(id);
	}
	void TaskCancel(uint64_t id)
	{
		_timer_wheel.TaskCancel(id);
	}
	bool hashTimer(uint64_t id)
	{
		return _timer_wheel.hashtimer(id);
	}

private:
	Poller poller;
	TimerWheel _timer_wheel;
	std::thread::id _thread_id;				 // eventloop所处线程id
	int _event_fd;							 // eventfd唤醒事件监控
	std::unique_ptr<Channel> _event_channel; // 管理eventfd事件监控
	std::vector<Functor> _tasks;			 // 任务池
	std::mutex _mutex;
};

void Channel::Remove()
{
	_loop->RemoveEvents(this);
}

void Channel::Update()
{
	_loop->UpdateEvents(this);
}
void TimerWheel::TaskAdd(uint64_t id, uint32_t timeout, const TaskFunc &task)
{
	_loop->RunInLoop(std::bind(&TimerWheel::TaskAddInLoop, this, id, timeout, task));
}
void TimerWheel::RefreshTask(uint64_t id)
{
	_loop->RunInLoop(std::bind(&TimerWheel::RefreshTaskInLoop, this, id));
}
void TimerWheel::TaskCancel(uint64_t id)
{
	_loop->RunInLoop(std::bind(&TimerWheel::TaskCancelInLoop, this, id));
}

// using Functor = std::function<void()>;

// class EventLoop
// {
// private:
// 	// 执行所有任务
// 	void RunAllLoop()
// 	{
// 		std::vector<Functor> tmp;
// 		{
// 			std::unique_lock<std::mutex> lock(_mutex);
// 			_tasks.swap(tmp);
// 		}
// 		for(auto &e : tmp)
// 		{
// 			e();
// 		}
// 	}
// 	//传教eventfd
// 	int CreateEventfd()
// 	{
// 		int fd = ::eventfd(0,EFD_CLOEXEC | EFD_NONBLOCK);
// 		if(fd < 0)
// 		{
// 			ERR_LOG("eventfd error，%d,%s",errno,strerror(errno));
// 			abort();
// 		}
// 		return fd;
// 	}
// 	void ReadEventfd()
// 	{
// 		uint64_t val = 0;
// 		int ret = ::read(_eventfd,&val,sizeof(val));
// 		if(ret < 0)
// 		{
// 			if(errno == EINTR || errno == EAGAIN)
// 			{
// 				return;
// 			}
// 			ERR_LOG("read error，%d,%s",errno,strerror(errno));
// 			abort();
// 		}
// 	}
// 	void WakeUpEventfd()
// 	{
// 		uint64_t val = 0;
// 		int ret = ::write(_eventfd,&val,sizeof(val));
// 		if(ret < 0)
// 		{
// 			if(errno == EINTR)
// 			{
// 				return;
// 			}
// 			ERR_LOG("write error，%d,%s",errno,strerror(errno));
// 			abort();
// 		}
// 	}
// public:
// 	EventLoop()
// 		:_timer_wheel(this),_thread_id(std::this_thread::get_id()),_eventfd(CreateEventfd())
// 		,_event_channel(new Channel(this,_eventfd))
// 	{
// 		_event_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd,this));
// 		_event_channel->EnableReadableEvent();
// 	}
// 	// 等待就绪事件，就绪事件处理，执行队列
// 	void Start()
// 	{
// 		std::vector<Channel*> active;
// 		_poller.OpenPoll(&active);
// 		for(auto &e : active)
// 		{
// 			e->HandlerEvent();
// 		}
// 		RunAllLoop();
// 	}
// 	// 判断当前线程是不是EventLoop对应的线程
// 	bool IsInLoop()
// 	{
// 		return _thread_id == std::this_thread::get_id();
// 	}
// 	// 把任务压入队列
// 	void QueueInLoop(const Functor &cd)
// 	{
// 		{
// 			std::unique_lock<std::mutex> lock(_mutex);
// 			_tasks.push_back(cd);
// 		}
// 		// 任务插入队列后，可能epoll_wait在阻塞等待事件就绪,所以要唤醒事件
// 		WakeUpEventfd();
// 	}
// 	// 判段当前任务在不在对应线程中，如果在直接执行，不在则压入队列
// 	void RunInLoop(const Functor &cd)
// 	{
// 		if(IsInLoop())
// 		{
// 			cd();
// 		}
// 		return QueueInLoop(cd);
// 	}
// 	void RemoveEvents(Channel *channel)
// 	{
// 		_poller.RemoveEvents(channel);
// 	}
// 	void UpdateEvents(Channel *channel)
// 	{
// 		_poller.UpdateEvents(channel);
// 	}
// 	// 添加定时任务
// 	void TaskAdd(uint64_t id, uint32_t timeout, const TaskFunc &task)
// 	{
// 		_timer_wheel.TaskAdd(id,timeout,task);
// 	}
// 	// 刷新定时任务
// 	void RefreshTask(uint64_t id)
// 	{
// 		_timer_wheel.RefreshTask(id);
// 	}
// 	// 取消定时任务
// 	void TaskCancel(uint64_t id)
// 	{
// 		_timer_wheel.TaskCancel(id);
// 	}
// 	bool hashTimer(uint64_t id)
// 	{
// 		return _timer_wheel.hashtimer(id);
// 	}
// private:
// 	Poller _poller;
// 	TimerWheel _timer_wheel;
// 	std::vector<Functor> _tasks;
// 	std::thread::id _thread_id;
// 	int _eventfd;                     // eventfd唤醒事件监控
// 	std::unique_ptr<Channel> _event_channel;
// 	std::mutex _mutex;
// };
